﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BTM_Client_Application.SupportClasses;
using Client_Server_Interface;
using Client_Server_Interface.Chat;

namespace BTM_Client_Application.Chat
{
    /// <summary>
    /// Логика взаимодействия для ChatControl.xaml
    /// </summary>
    public partial class ChatControl : UserControl, IDisposable
    {

        #region events

        public event VoidIntDelegate UnreadMessage;

        protected virtual void OnUnreadMessage(int a)
        {
            VoidIntDelegate handler = UnreadMessage;
            if (handler != null) handler(a);
        }

        #endregion

        private ObservableCollection<TabItem> _windows;
        private string _general;
        private int _unreadMessagesCount;

        public ChatControl()
        {
            InitializeComponent();
            Init();
        }

        public bool IsThisVisible { get; set; }
        public bool CurUserOnline { get; set; }
        public string CurUser { get; set; }

        public void UiLanguageChanged()
        {
            UsersListLabel.Content = Res.Rm.GetString("UsersList", AliveInfo.CurrentCulture);
            SendButtonTitle.Text = Res.Rm.GetString("Send", AliveInfo.CurrentCulture);

            _general = Res.Rm.GetString("General", AliveInfo.CurrentCulture);

            _windows[0].Header = _general;

        }

        public void Init()
        {
            IsThisVisible = false;
            CurUserOnline = true;
            CurUser = _general;
            _unreadMessagesCount = 0;
            //Create Send Command
            //var myCommand1 = new RoutedCommand();
            //CommandBindings.Add(new CommandBinding(myCommand1, SendButton_OnClick));
            //myCommand1.InputGestures.Add(new KeyGesture(Key.Enter, ModifierKeys.Control));
            ChangeSendState(true);
            Thread.CurrentThread.CurrentUICulture = AliveInfo.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = AliveInfo.CurrentCulture;
            //Chat init
            try
            {
                AliveInfo.Chat.Start();
                AliveInfo.Chat.NewNames += ChatOnNewNames;
                AliveInfo.Chat.ReceiveMsg += ChatOnReceiveMsg;
            }
            catch (Exception)
            {
                //AliveInfo.ClientEvents.AddEvent(Res.Rm.GetString("ChatError", AliveInfo.CurrentCulture), ex.Message);
                throw;
            }
            
            //Tabs init
            _windows = new ObservableCollection<TabItem>();
            ChatWindows.ItemsSource = _windows;
            _general = Res.Rm.GetString("General", AliveInfo.CurrentCulture);
            var ti = new TabItem
                {
                    Header = _general,
                    Content = new ChatWindow(_general),
                    IsSelected = true,
                    FontFamily = new FontFamily("SegoeUI"),
                };
            _windows.Add(ti);

            UiLanguageChanged();

        }

        //ToImplement
        private void ChatOnReceiveMsg(string sender, string message)
        {

            if(sender == AliveInfo.Chat.Name)
                return;

            if(!IsThisVisible)
                if(CurUser != sender)
                    OnUnreadMessage(_unreadMessagesCount);

            var cl = ClientMessage.DeserializeMessage(message);
            cl.Sender = sender;
            cl.Side = MessageSide.You;
            cl.Receiver = AliveInfo.Chat.Name;

            AddMessageUi(cl);
        }

        private void ChatOnNewNames(object sender, List<string> names)
        {
            //Убираем свое имя из списка
            names.Remove(AliveInfo.Chat.Name);
            //UserContainer.ItemsSource = NamesToUsers(names);
            UserContainer.ItemsSource = new ObservableCollection<string>(names);

            ICollectionView dataView = CollectionViewSource.GetDefaultView(UserContainer.ItemsSource);
            dataView.SortDescriptions.Clear();
            var sd = new SortDescription("ToString()", ListSortDirection.Ascending);
            dataView.SortDescriptions.Add(sd);
            dataView.Refresh();

            foreach (TabItem tab in ChatWindows.Items)
            {
                if (tab.Header.ToString() == _general)
                    continue;
                var name = names.FirstOrDefault(n => n.ToString(CultureInfo.InvariantCulture) == tab.Header.ToString());
                if (name != null)
                {
                    var cw = tab.Content as ChatWindow;
                    if (!cw.Online)
                        cw.Online = true;
                    if (tab.IsSelected)
                    {
                        ChangeSendState(true);
                    }
                }
                else
                {
                    var cw = tab.Content as ChatWindow;
                    if (cw.Online)
                        cw.Online = false;
                    if (tab.IsSelected)
                    {
                        ChangeSendState(false);
                    }
                    //AliveInfo.Sounds[Sound.UserLeft].Play();
                }
            }

            //var view = (CollectionView)CollectionViewSource.GetDefaultView(UserContainer.ItemsSource);
            //view.SortDescriptions.Add(new SortDescription("UserName", ListSortDirection.Ascending));
        }

        private void AddMessageUi(ClientMessage cm)
        {

            TabItem win = null;
            if (!cm.IsPrivate)
            {
                win = _windows.FirstOrDefault(x => x.Header.ToString() == _general);
                if (DetermineReceiver() != _general)
                    win.DataContext = new TabHeaderProp();
            }
            else if (cm.Sender == AliveInfo.Chat.Name)
            {
                win = _windows.FirstOrDefault(x => x.Header.ToString() == cm.Receiver);
            }
            else if (cm.Receiver == AliveInfo.Chat.Name)
            {
                win = _windows.FirstOrDefault(x => x.Header.ToString() == cm.Sender);
            }
            if (win == null)
            {
                win = AddUserTab(cm.Sender, new ChatWindow(cm.Sender));
                //win.DataContext = new TabHeaderProp() { NewMessage = true };
            }
            if (cm.Sender != AliveInfo.Chat.Name)
            {
                if (cm.Sender != DetermineReceiver())
                {
                        win.DataContext = new TabHeaderProp();
                }
                //(win.Header as Control).Background = new SolidColorBrush(Colors.Orange);
            }
            var cw = win.Content as ChatWindow;
            if (cm.Side == MessageSide.Me)
                cm.Sender = Res.Rm.GetString("Me", AliveInfo.CurrentCulture);
            
            cw.MesItems.Add(cm);    

            //string sender;
            //if (!cm.IsPrivate)
            //{
            //    sender = _general;
            //}
            //else
            //    sender = cm.Sender;

            //var win = _windows.FirstOrDefault(x => x.Header.ToString() == sender);

            //if (win == null)
            //{
            //    win = AddUserTab(sender, new ChatWindow(sender));
            //}

            //var cw = win.Content as ChatWindow;
            //if (cm.Side == MessageSide.Me)
            //    cm.Sender = Res.Rm.GetString("Me", AliveInfo.CurrentCulture);
            //cw.MesItems.Add(cm);
        }

        private IEnumerable<User> NamesToUsers(IEnumerable<string> names)
        {
            var toRet = new ObservableCollection<User>();
            foreach (var name in names)
            {
                toRet.Add(new User(name));
            }
            return toRet;
        }

        public void Dispose()
        {
            AliveInfo.Chat.Stop();
        }

        private void SendButton_OnClick(object sender, RoutedEventArgs e)
        {
            //var receiver = DetermineReceiver();
            var receiver = CurUser;

            var m = new ClientMessage
                {
                    TimeStamp = DateTime.Now,
                    Message = WriteBox.Text,
                    IsPrivate = true
                };

            if (receiver == _general)
            {
                receiver = FunctionsParameters.GENERAL_MESSAGE;
                m.IsPrivate = false;
            }
            AliveInfo.Chat.SendMessage(m.Serialize(), receiver);
            m.Sender = AliveInfo.Chat.Name;
            m.Receiver = receiver;
            AddMessageUi(m);
            WriteBox.Clear();
            
        }

        void ChangeSendState(bool enabled)
        {
            if (enabled)
            {
                SendButton.IsEnabled = true;
                var myCommand1 = new RoutedCommand();
                CommandBindings.Add(new CommandBinding(myCommand1, SendButton_OnClick));
                myCommand1.InputGestures.Add(new KeyGesture(Key.Enter, ModifierKeys.Control));
            }
            else
            {
                SendButton.IsEnabled = false;
                CommandBindings.Clear();
            }
        }

        private string DetermineReceiver()
        {
            var ti = ChatWindows.SelectedItem as TabItem;
            return ti.Header.ToString();
        }

        private void UserContainer_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var view = sender as ListBox;
            var u = view.SelectedItem.ToString();

            var win = _windows.FirstOrDefault(x => x.Header.ToString() == u);

            if (win == null)
            {
                win = AddUserTab(u, new ChatWindow(u));
            }

            win.IsSelected = true;
        }

        private TabItem AddUserTab(string header, ChatWindow content)
        {
            var win = new TabItem { Header = header, Content = content, FontFamily = new FontFamily("SegoeUI")};
            win.MouseDoubleClick += WinOnMouseDoubleClick;
            _windows.Add(win);
            return win;
        }

        private void RemoveUserTab(TabItem tab)
        {
            _windows.Remove(tab);
        }

        private void WinOnMouseDoubleClick(object sender, MouseButtonEventArgs mouseButtonEventArgs)
        {
            var tabItem = (sender as TabItem);
            var mo = (tabItem.Content as UIElement).IsMouseOver;
            if (!mo)
                RemoveUserTab(sender as TabItem);
        }

        private void ChatWindows_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var tabs = sender as TabControl;
            var chatw = tabs.SelectedItem as TabItem;
            if(chatw == null)
                return;
            CurUser = chatw.Header.ToString();
            chatw.DataContext = null;
            var cw = chatw.Content as ChatWindow;
            CurUserOnline = cw.Online;
            ChangeSendState(cw.Online);
        }

        class TabHeaderProp
        {
            public bool NewMessage { get; set; }

            public TabHeaderProp()
            {
                NewMessage = true;
            }
        }

    }
}
